﻿using PerpheralDevice.IRepository;
using PerpheralDevice.Units;
using System.Serialization;

namespace AppMachine.Domain.LogicCom.AppComs;

/// <summary>
/// 应用组件(伺服运动组件)
/// </summary>
public class ComMotor(IPerpDevRepository perpDevRepository, IComConfig comConfig, IComRepository comRepository) 
                : AppComPrim(perpDevRepository, comConfig, comRepository) {

    private readonly ComMotorParam mfComMotorParam = YamlExtend.GetObject<ComMotorParam>(comConfig.ComParamSerialized) ?? new();

    /// <summary>
    /// 物理运动伺服
    /// </summary>
    public Motor Motor => this.PerpDev.Find<Motor>(this.ComConfig.PerpSeatID!);
    public ComMotor ReachAbs(int posDst) {

        return this;
    }
    public ComMotor ReachRel(double posDst) {
        if (!this.PerpDev.IsMocking) {
            this.Motor.ReachRel(this.UnitToPulse(posDst));
        }
        return this;
    }

    /// <summary>
    /// 回零
    /// </summary>
    /// <returns></returns>
    public ComMotor Reset() {
        this.Motor.Reset();
        return this;
    }

    /// <summary>
    /// 进行连续运动，需要主动Stop才能停止(点动)
    /// </summary>
    /// <param name="dirMoveIsForward">运动方向是否为正</param>
    /// <returns></returns>
    public ComMotor DoMoving(bool dirMoveIsForward = true) {
        this.Motor.DirMoveIsForwardSet(dirMoveIsForward).DoMoving();
        return this;
    }

    /// <summary>
    /// 停止运动
    /// </summary>
    /// <returns></returns>
    public ComMotor Stop() {
        this.Motor.Stop();
        return this;
    }

    /// <summary>
    /// 根据应用配置(螺距、电机齿轮比(放大系数)) 运动位置 转为 脉冲位置
    /// </summary>
    /// <returns>单位位置(当量: 每个单位需要的脉冲数量)</returns>
    private int UnitToPulse(double unit) => (int)(unit * this.mfComMotorParam!.GearRatio / this.mfComMotorParam!.TPitch);
    /// <summary>
    /// 根据应用配置(螺距、电机齿轮比(放大系数)) 脉冲位置 转为 运动位置
    /// </summary>
    /// <returns>脉冲位置(当量: 每个单位需要的脉冲数量)</returns>
    private double PulseToUnit(int pulse) => pulse * this.mfComMotorParam!.TPitch / this.mfComMotorParam!.GearRatio;

    /// <summary>
    /// 轴的应用方向(X轴，Y轴，Z轴，R轴，C轴)
    /// </summary>
    public string AppType => this.mfComMotorParam.AppType;

    /// <summary>
    /// 工作速度(矢量)
    /// </summary>
    public double VelWork => this.mfComMotorParam.VelWork;
    public ComMotor VelWorkSet(double velWork) {
        this.mfComMotorParam!.VelWork = velWork;        
        return this;
    }

    /// <summary>
    /// 回零速度(矢量)
    /// </summary>
    public double VelReset => this.mfComMotorParam.VelReset;
    public ComMotor VelResetSet(double velReset) {
        this.mfComMotorParam.VelReset = velReset;
        return this;
    }

    /// <summary>
    /// 回零 爬行 速度(矢量)
    /// </summary>
    public double VelCrawl => this.mfComMotorParam.VelCrawl;
    public ComMotor VelCrawlSet(double velCrawl) {
        this.mfComMotorParam.VelCrawl = velCrawl;
        return this;
    }

    public double VelSeek => this.mfComMotorParam.VelSeek;
    /// <summary>
    /// 设置点动速度(矢量)
    /// </summary>
    /// <param name="velSeek">点动速度</param>
    /// <returns></returns>
    public ComMotor VelSeekSet(double velSeek) {
        this.mfComMotorParam.VelSeek = velSeek;
        return this;
    }

    /// <summary>
    /// 行程范围起点
    /// </summary>
    public double StrokeBeg => this.mfComMotorParam.StrokeBeg;
    public ComMotor StrokeBegSet(double strokeBeg) {
        this.mfComMotorParam.StrokeBeg = strokeBeg;
        return this;
    }

    /// <summary>
    /// 行程范围终点
    /// </summary>
    public double StrokeEnd => this.mfComMotorParam.StrokeEnd;
    public ComMotor StrokeEndSet(double strokeEnd) {
        this.mfComMotorParam.StrokeEnd = strokeEnd;
        return this;
    }

    /// <summary>
    /// 闲置位置
    /// </summary>
    public double PosIdle => this.mfComMotorParam.PosIdle;
    public ComMotor PosIdleSet(double posIdle) {
        this.mfComMotorParam.PosIdle = posIdle;
        return this;
    }

    /// <summary>
    /// 螺距/导程
    /// </summary>
    public int TPitch => this.mfComMotorParam.TPitch;
    public ComMotor TPitchSet(int tPitch) {
        this.mfComMotorParam.TPitch = tPitch;
        return this;
    }

    /// <summary>
    /// 电子齿轮比率
    /// </summary>
    public int GearRatio => this.mfComMotorParam.GearRatio;
    public ComMotor GearRatioSet(int gearRatio) {
        this.mfComMotorParam.GearRatio = gearRatio;
        return this;
    }

    public override AppCom Save() {
        (this.ComConfig as AppComConfig)!.ComParamSerialized = YamlExtend.GetString(this.mfComMotorParam);
        return base.Save();
    }

}
